<?php
declare (strict_types=1);

namespace app\common\queue\promotion;

use app\common\exception\LogicException;
use app\common\model\payment\{PaymentOrder as PO, PaymentOrderItem as POI};
use app\promotion\logic\{PromotionTuan as TuanLogic, PromotionTuanData as TuanData};
use app\user\logic\user\{Balance, Credit};
use eduline\payment\Pay;
use Exception;
use think\annotation\Inject;
use think\facade\{Db};
use Yansongda\Pay\Exceptions\BusinessException;

/**
 * 拼团类
 */
class Tuan
{
    /**
     * @Inject()
     * @var TuanLogic
     */
    protected $tuanLogic;

    /**
     * @throws Exception
     */
    public function run()
    {
        try {
            // 清理假删除数据
            $this->tuanLogic->onlyTrashed()->select()->each(function ($i) {
                if (!$i->status) $i->force()->delete();
            });
            app(TuanData::class)->onlyTrashed()->select()->each(function ($i) {
                if (!$i->status) $i->force()->delete();
            });

            $time   = time();
            $failed = $this->tuanLogic->getFailedUnrefundTuan();

            if ($failed->isEmpty()) return;

            foreach ($failed as $tuan) {
                Db::startTrans();
                try {
                    // 修改开团状态
                    $tuan              = $this->tuanLogic->findOrEmpty($tuan->id);
                    $tuan->status      = 3;
                    $tuan->delete_time = $time;
                    if (!$tuan->save()) throw new LogicException("状态处理错误");
                    // 处理退款
                    $tuan_data = app(TuanData::class)->whereTuanId($tuan->id)->select();
                    if (!$tuan_data->isEmpty()) {
                        foreach ($tuan_data as $data) {
                            $data->status      = 3;
                            $data->delete_time = $time;
                            if (!$data->save()) throw new LogicException("入团状态处理失败");
                            // 支付方式
                            $order_item = app(POI::class)->alias('i')->join('payment_transaction t', 'i.order_no=t.order_no')->where('order_sub_no', $data->order_sub_no)->field('payment_type,t.payment,t.order_no')->where('t.user_id', $data->user_id)->where('promotion_id', $tuan->promotion_id)->with(['order_status'])->findOrEmpty()// ->buildSql()
                            ;
                            // echo 'order_item:'.$order_item;
                            if (!$order_item->isEmpty() && in_array($order_item->status, [10, 80])) {
                                if (80 == $order_item->status) {
                                    // 退款参数
                                    switch ($order_item->payment_type) {
                                        case 'alipay':
                                            $refund_param = [
                                                'out_trade_no'  => $order_item->order_no,
                                                'refund_amount' => $order_item->payment
                                            ];
                                            // 退款申请
                                            $re = Pay::alipay()->refund($refund_param);
                                            if ($re->code != "10000" || $re->msg != "Success") throw new LogicException("退款申请失败");
                                            // 退款查询
                                            $re = Pay::alipay()->find(['out_trade_no' => $order_item->order_no]);
                                            if ($re->code != "10000" || $re->msg != "Success") throw new LogicException("退款失败");
                                            break;

                                        case 'wxpay':
                                            $refund_param = [
                                                'out_trade_no'  => $order_item->order_no,
                                                'out_refund_no' => $order_item->order_no,
                                                'total_fee'     => $order_item->payment,
                                                'refund_fee'    => $order_item->payment,
                                                'refund_desc'   => '课程退款',
                                            ];
                                            // 退款申请
                                            $re = Pay::wxpay()->refund($refund_param);
                                            if ($re->return_code != "SUCCESS" || $re->result_code != "SUCCESS") throw new LogicException("退款申请失败");
                                            // 退款查询
                                            $re = Pay::wxpay()->find(['out_trade_no' => $order_item->order_no]);
                                            if ($re->return_code != "SUCCESS" || $re->result_code != "SUCCESS") throw new LogicException("退款失败");
                                            break;

                                        case 'lcnpay':
                                            app(Balance::class)->increaseUserBalance($data->user_id, 13, $order_item->payment, 'payment_order', $order_item->order_no, '退款：' . $order_item->payment);
                                            break;

                                        default:
                                            # code...
                                            break;
                                    }
                                }
                                // 订单状态
                                $order = app(PO::class)->with(['redeem_credit_sub'])->where('order_no', $order_item->order_no)->findOrEmpty();
                                if ($order->isEmpty()) throw new LogicException("订单查询失败");
                                $order->status = $order->status == 80 ? 50 : 60;
                                if (!$order->save()) throw new LogicException("订单退款状态处理失败");
                                // 订单积分退还
                                if ($order_item->credit) {
                                    app(Credit::class)->returnOrderCredit($order);
                                }
                            }
                        }
                    }
                    Db::commit();
                } catch (LogicException|Exception $e) {
                    Db::rollback();
                    throw new LogicException($e->getMessage());
                }
            }
        } catch (Exception $e) {
            throw new BusinessException($e->getFile() . $e->getLine() . $e->getMessage());
        }
    }
}
